/*
  校门外的树（增强版）
  题目描述
    校门外马路上本来从编号 1 到 L，每一编号的位置都有一棵树。
    有砍树者每次从编号 A 到 B 处连续砍掉每一棵树，就连树苗也不放过（记作 0 A B，含 A 和 B）;
    幸运的是还有植树者每次从编号 C 到 D 中凡是空穴（树被砍且还没种上树苗或树苗又被砍掉）
      的地方都补种上树苗（记作 1 C D，含 C 和 D）;

    问最终校门外留下的树苗多少棵？植树者种上又被砍掉的树苗有多少棵？
  输入描述
    第一行，两个正整数 L 和 N，表示校园外原来从编号 1 到 L 有 L 棵树，并有 N 次砍树或种树的操作。
    接下来 N 行，每行三个整数，表示砍树或植树的标记和范围。
  输出描述
    共两行。第一行校门外留下的树苗数目，第二行种上又被拔掉的树苗数目。
  样例1
    输入
      10 3
      0 2 6
      1 1 8
      0 5 7
    输出
      3
      2
  提示
    对于 100% 的数据，1 <= L <= 10000，1 <= N <= 100
*/

#include <bits/stdc++.h>

using namespace std;

int main() {
    /*
       tree[i] 表示编号为 i 的位置上树的状态
           0 = 未被砍伐
           1 = 树被砍伐
           2 = 新的树苗
       对应的状态转换图(状态机)如下:
                       砍树               种树苗
           0 (未被砍) -------> 1 (树被砍) ------->  2 (新的树苗)
                                         <-------
                                          砍树
    */
    int tree[10001] = {};
    int cnt = 0;
    int l, n, a, b, c;

    cin >> l >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a >> b >> c;
        if (a == 0) { // 砍掉编号 b ~ 编号 c 的位置上的的树(包括编号 b 和 编号 c 的位置上的树)
            for (int j = b; j <= c; j++) {
                if (tree[j] == 2) {  // 如果对应位置上是新的树苗, 则为 种上又被砍掉的树 进行加 1 计数
                    cnt ++;
                }
                tree[j] = 1;  // 标记对应位置上的树已被砍伐
            }
        } else {     // 在编号 b ~ 编号 c 的位置上种树
            for (int j = b; j <= c; j++) {
                if (tree[j] == 1) {   // 如果对应位置上树已被砍伐, 则在该位置种上新的树苗
                    tree[j] = 2;
                }
            }
        }
    }

    int x = 0;
    for (int i = 1; i <= l; i++) {
        if (tree[i] == 2) { // 统计树苗的个数
            x++;
        }
    }
    cout << x <<endl <<  cnt;

    return 0;
}